using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using Bbc.Scrobblers;
using Scrobbler.UI.WF.Interfaces;

namespace Scrobbler.UI.WF.Presenters
{
    public class MainWindowPresenter
    {
        private readonly IMainWindow _view;
        public Conf Conf { get; set; }
        private Processor _processor;
        private BackgroundWorker _scrobblerWorker;

        public MainWindowPresenter(IMainWindow mainWindow)
        {
            _view = mainWindow;
        }

        #region Public Methods

        public void InitConfig()
        {
            IConfiguration cfg = new Configuration();

            if (!File.Exists(GlobalConfiguration.ConfigurationPath)) { cfg.Save(GlobalConfiguration.ConfigurationPath); }
            else { cfg = ConfigurationHandler.Load(GlobalConfiguration.ConfigurationPath); }

            Conf = new Conf { Configuration = cfg, StreamSources = RegisterStreamSources() };
            GlobalConfiguration.Configuration = cfg;
        }

        public object GetRadiosDataSource()
        {
            return Conf.StreamSources;
        }

        public void Scrobble()
        {
            var radio = _view.GetRadio();

            if (radio != null)
            {
                _scrobblerWorker = new BackgroundWorker { WorkerSupportsCancellation = true };
                _view.UpdateUiOnScrobbling();
                _scrobblerWorker.DoWork += (o, args) => ScrobblerWorkerOnDoWork(radio, args);
                _scrobblerWorker.RunWorkerAsync();
            }
        }

        public void StopScrobbling()
        {
            if (_processor != null)
            {
                _processor.StopProcessing();
            }

            _view.UpdateUiWaitingForFinishingAction();

            if (_scrobblerWorker != null)
            {
                _scrobblerWorker.RunWorkerCompleted += ScrobblerWorkerOnRunWorkerCompleted;
                _scrobblerWorker.CancelAsync();
            }
        }

        public void OpenInBrowser()
        {
            var radio = _view.GetRadio();

            if (radio != null && !string.IsNullOrEmpty(radio.Url))
            {
                Process.Start(radio.Url);
            }
        }

        public void GoToWebsite()
        {
            Process.Start(GlobalConfiguration.AppWebsite);
        }

        #endregion

        #region Private Methods

        private IDictionary<Type, string> RegisterStreamSources()
        {
            var sources = new Dictionary<Type, string>
                              {
                                                        { typeof (BbcRadio1StreamSource), "BBC Radio 1" },
                                                        { typeof (BbcRadio1XtraStreamSource), "BBC Radio 1Xtra" },
                                                        { typeof (BbcRadio2StreamSource), "BBC Radio 2" },
                                                        { typeof (BbcRadio6MusicStreamSource), "BBC Radio 6 Music" }
                                                    };
            return sources;
        }

        private void ScrobblerWorkerOnDoWork(IStreamSource radio, DoWorkEventArgs doWorkEventArgs)
        {
            _processor = new Processor();
            _processor.ErrorOccured += ProcessorOnErrorOccured;
            _processor.SongScrobbled += ProcessorOnSongScrobbled;

            radio.SongChanged += RadioOnSongChanged;
            radio.ErrorOccured += ProcessorOnErrorOccured;

            _processor.StartProcessing(radio);
        }

        private void RadioOnSongChanged(object sender, SongEventArgs args)
        {
            _view.UpdateSongInfo(args.Song.ToString());
        }

        private void ProcessorOnSongScrobbled(object sender, ProcessorEventArgs args)
        {
            var text = string.Format("[{0}] {1}", DateTime.Now.ToString("hh:MM:ss"), args.Message);
            _view.SetStatus(text);
        }

        private void ProcessorOnErrorOccured(object sender, ProcessorEventArgs args)
        {
            var text = string.Format("[{0}] {1}", DateTime.Now.ToString("hh:MM:ss"), args.Message);
            _view.SetStatus(text);
        }

        private void ScrobblerWorkerOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs)
        {
            _processor = null;
            _view.UpdateUiOnNotScrobbling();
        }

        #endregion
    }
}